﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using rusisControls.MVC.Models;
using System.Web.Routing;
using System.Globalization;
using rusisControls.MVC.Controls.rusisGrid;
using System.Data.Entity;

namespace System.Web.Mvc.Html
{
    public static class rusisGridHelper
    {
        public static MvcHtmlString rusisGrid<TModel>(this HtmlHelper helper, PagedViewModel<TModel> Model, RouteValueDictionary fields, string actionName, string controllerName, IDictionary<string, object> htmlAttributes = null)
            where TModel : class
        {

            //rsGridNavigation(
            //this HtmlHelper helper, 
            //int currentPage, 
            //int pageCount, 
            //RouteValueDictionary currentRouteValues
            //)

            // ================================================
            // пример вызова хэлпера навигации:
            // ================================================
            //@Html.rsGridNavigation(
            //    Model.Page ?? 1,
            //    (((Model.TotalCount ?? 0) - 1) / (Model.PageSize ?? 10) + 1),
            //    new RouteValueDictionary(new
            //    {
            //        start = (Model.Page - 1) * Model.PageSize,
            //        itemsPerPage = Model.PageSize,
            //        orderBy = Model.GridSortOptions.Column,
            //        desc = Model.GridSortOptions.Direction,
            //        Id = ViewData["Id"],
            //        EnterDate = ViewData["EnterDate"],
            //        SNILS = ViewData["SNILS"],
            //        LastName = ViewData["LastName"],
            //        FirstName = ViewData["FirstName"],
            //        Patronimyc = ViewData["Patronimyc"]
            //    })
            //)

            
// ------------------------------------------------------------------------------------------------------------------ //

            //rsGridSearchBox(
            //this HtmlHelper helper, 
            //string actionName, 
            //string controllerName, 
            //int countColumns, 
            //RouteValueDictionary fields, 
            //RouteValueDictionary hiddenFields
            //)

            // ================================================
            // пример вызова хэлпера блока с полями поиска:
            // ================================================
            //@Html.rsGridSearchBox(
            //    "EnterToPO",
            //    "HistoryOperations",
            //    7,
            //    new RouteValueDictionary(new
            //    {
            //        Id = ViewData["Id"],
            //        EnterDate = (ViewData["EnterDate"] == null ? DateTime.MinValue : ViewData["EnterDate"]),
            //        SNILS = ViewData["SNILS"],
            //        LastName = ViewData["LastName"],
            //        FirstName = ViewData["FirstName"],
            //        Patronimyc = ViewData["Patronimyc"]
            //    }),
            //            new RouteValueDictionary(new
            //            {
            //                start = (Model.Page - 1) * Model.PageSize,
            //                itemsPerPage = Model.PageSize,
            //                orderBy = Model.GridSortOptions.Column,
            //                desc = (Model.GridSortOptions.Direction == MvcContrib.Sorting.SortDirection.Ascending) ? MvcContrib.Sorting.SortDirection.Descending : MvcContrib.Sorting.SortDirection.Ascending
            //            })
            //        )

            #region блок названий CSS-классов для всех элементов грида
            
            // CSS-классы для блока навигации по гриду
            string rsGridNavigationCSS = "rsGridNavigation";
            string rsBeginLinkCSS = "rsBeginLink";
            string rsPrevLinkCSS = "rsPrevLink";
            string rsPageNumCSS = "rsPageNum";
            string rsPageCountCSS = "rsPageCount";
            string rsNextLinkCSS = "rsNextLink";
            string rsEndLinkCSS = "rsEndLink";
            string rsItemsPerPageCSS = "rsItemsPerPage";
            string rsGridNavigationPageCSS = "rsGridNavigationPage";


            #endregion блок названий CSS-классов для всех элементов грида


            var urlHelper = new UrlHelper(helper.ViewContext.Controller.ControllerContext.RequestContext);

            StringBuilder builder = new StringBuilder();

            RouteValueDictionary TMP_ROUTE = new RouteValueDictionary();
            TMP_ROUTE.Add("start", (Model.Page - 1) * Model.PageSize);
            TMP_ROUTE.Add("itemsPerPage", Model.PageSize);
            TMP_ROUTE.Add("desc", (Model.GridSortOptions.Direction == SortDirection.Ascending) ? SortDirection.Descending : SortDirection.Ascending);
            TMP_ROUTE.Add("orderBy", Model.GridSortOptions.Column);
            foreach (var field in fields)
                TMP_ROUTE.Add(field.Key, Model.ViewData[field.Key]);

            // ================================================
            // Формируется Навигация по гриду
            // ================================================
            #region Формируется Навигация по гриду

            int currentStart = (int)TMP_ROUTE["start"];
            int itemsPerPage = (int)TMP_ROUTE["itemsPerPage"];
            int currentPage = Model.Page ?? 1;
            int pageCount = (((Model.TotalCount ?? 0) - 1) / (Model.PageSize ?? 10) + 1);

            builder.AppendLine("    <div class='" + rsGridNavigationCSS + "'>");
            builder.AppendLine("    <div class='" + rsGridNavigationPageCSS + "'>");
            if (currentPage != 1)
            {
                TMP_ROUTE["start"] = 0;
                builder.AppendLine("            <a href=\"" + urlHelper.RouteUrl(TMP_ROUTE) + "\" class=\"" + rsBeginLinkCSS + "\">|&lt;</a>");
                TMP_ROUTE["start"] = currentStart - itemsPerPage;
                builder.AppendLine("            &nbsp;&nbsp;<a href=\"" + urlHelper.RouteUrl(TMP_ROUTE) + "\" class=\"" + rsPrevLinkCSS + "\">&lt;&lt;</a>");
            }
            else
            {
                builder.AppendLine("            <span class=\"" + rsBeginLinkCSS + "\">|&lt;</span>&nbsp;&nbsp;<span class=\"" + rsPrevLinkCSS + "\">&lt;&lt;</span>");
            }

            builder.AppendLine("        &nbsp;&nbsp;<span>Страница</span>&nbsp;<span class=\"" + rsPageNumCSS + "\">" + currentPage.ToString() + "</span>&nbsp;<span>из</span>&nbsp;<span class=\"" + rsPageCountCSS + "\">" + pageCount.ToString() + "</span>&nbsp;&nbsp;");
            if (currentPage != pageCount)
            {
                TMP_ROUTE["start"] = currentStart + itemsPerPage;
                builder.AppendLine("            <a href=\"" + urlHelper.RouteUrl(TMP_ROUTE) + "\" class=\"" + rsNextLinkCSS + "\">&gt;&gt;</a>");
                TMP_ROUTE["start"] = (pageCount - 1) * itemsPerPage;
                builder.AppendLine("            &nbsp;&nbsp;<a href=\"" + urlHelper.RouteUrl(TMP_ROUTE) + "\" class=\"" + rsEndLinkCSS + "\">&gt;|</a>");
            }
            else
            {
                builder.AppendLine("            <span class=\"" + rsNextLinkCSS + "\">&gt;&gt;</span>&nbsp;&nbsp;<span class=\"" + rsEndLinkCSS + "\">&gt;|</span>");
            }
            builder.AppendLine("    </div>");
            builder.AppendLine("    </div>");

            TMP_ROUTE["start"] = currentStart;
            builder.AppendLine("    <div class=\"" + rsItemsPerPageCSS + "\">");
            builder.AppendLine("        Строк на странице:");
            builder.AppendLine("            <select id=\"itemsPerPage\" name=\"itemsPerPage\" onChange='redirectWidthNewPageSize(\"" + urlHelper.RouteUrl(TMP_ROUTE) + "\", this)'>");
            builder.AppendLine("                <option value=\"10\"" + ((10 == (int)TMP_ROUTE["itemsPerPage"]) ? " selected " : "") + ">10</option>");
            builder.AppendLine("                <option value=\"20\"" + ((20 == (int)TMP_ROUTE["itemsPerPage"]) ? " selected " : "") + ">20</option>");
            builder.AppendLine("                <option value=\"50\"" + ((50 == (int)TMP_ROUTE["itemsPerPage"]) ? " selected " : "") + ">50</option>");
            builder.AppendLine("                <option value=\"100\"" + ((100 == (int)TMP_ROUTE["itemsPerPage"]) ? " selected " : "") + ">100</option>");
            builder.AppendLine("            </select>");
            builder.AppendLine("    </div>");
            builder.AppendLine("    <script>");
            builder.AppendLine("        function redirectWidthNewPageSize(currentRouteValues, select) {");
            builder.AppendLine("            selectedValue = select.options[select.selectedIndex].value; // Выбранное значение количества строк грида на экране");
            builder.AppendLine("	        var tmp = new Array();      // два вспомагательных");
            builder.AppendLine("	        var tmp2 = new Array();     // массива");
            builder.AppendLine("	        var param = new Array();");
            builder.AppendLine("	        newUrl = \"\";");
            builder.AppendLine("	        tmp = (currentRouteValues.substr(0)).split('&');   // разделяем переменные");
            builder.AppendLine("	        for(var i=0; i < tmp.length; i++)");
            builder.AppendLine("	        {");
            builder.AppendLine("	            tmp2 = tmp[i].split('=');       // массив param будет содержать");
            builder.AppendLine("	            if (tmp2[0] == \"itemsPerPage\")");
            builder.AppendLine("	                tmp2[1] = selectedValue; // Если нашелся параметр itemsPerPage, то присваиваем новое значение");
            builder.AppendLine("                param[tmp2[0]] = tmp2[1];       // пары ключ(имя переменной)->значение");
            builder.AppendLine("	        }");
            builder.AppendLine("            // Формирование нового Url с измененным параметром itemsPerPage");
            builder.AppendLine("	        for (var key in param)");
            builder.AppendLine("	        {");
            builder.AppendLine("	            newUrl = newUrl + key + \"=\" + param[key] + \"&\";");
            builder.AppendLine("	        }");
            builder.AppendLine("	        newUrl = newUrl.substr(0, (newUrl.length-1));");
            builder.AppendLine("	        window.location = newUrl;");
            builder.AppendLine("        }");
            builder.AppendLine("    </script>");

            #endregion Формируется Навигация по гриду

// ---------------------------------------------------------------------------------------------------------- //

            builder.AppendLine("<table width=\"100%\">");

            // ================================================
            // Формируется строка с заголовком и поиском (форма GET)
            // ================================================
            #region Формируется строка с заголовком и поиском (форма GET)

            builder.AppendLine("<script>");
            builder.AppendLine("    $(document).keypress(function(event) {");
            builder.AppendLine("        var keycode = (event.keyCode ? event.keyCode : event.which);");
            builder.AppendLine("        if (keycode == '13') {");
            builder.AppendLine("            $('#btnSearch').click();");
            builder.AppendLine("        }");
            builder.AppendLine("    });");
            builder.AppendLine("</script>");

            //string url = (helper.ViewContext.HttpContext.Request).RawUrl;
            builder.AppendLine("<form action=\"" + urlHelper.Action(actionName, controllerName) + "\" id=\"searchFrom\" method=\"get\">");
            //builder.AppendLine("<form action=\"" + url + "\" id=\"searchFrom\" method=\"get\">");
            builder.AppendLine("    <tr>");

            int colNum = 0;
            foreach (var field in fields)
            {
                colNum++;
                
                string style = "style=\"width:100px;\"";
                if (colNum == 1)
                    style = "style=\"width:30px;\"";

                builder.AppendLine("        <th style=\"white-space:nowrap;\">");

                if ((field.Value != null) && (field.Value.GetType() == typeof(DateTime))) // Если столбец - дата
                {
                    DateTime? value = null;
                    if ((DateTime)field.Value == DateTime.MinValue) // Значение сделать равным - null
                        value = null;
                    else // Контролу присвоить значение из field.Value
                        value = (DateTime)field.Value;

                    // Отрисовка контрола DatePicker
                    DateTimeFormatInfo dateTimeFormat = null;
                    CultureInfo cultureInfo = new CultureInfo("ru-RU");
                    //string dateFormatString = (dateTimeFormat ?? Thread.CurrentThread.CurrentCulture.DateTimeFormat).ShortDatePattern;
                    string dateFormatString = (dateTimeFormat ?? cultureInfo.DateTimeFormat).ShortDatePattern;
                    string dateFormatStringJQ = rusisDatePickerHelper.ConvertDateFormat(helper, dateFormatString);

                    builder.AppendLine(
                        "<script type='text/javascript'> " +
                                " $(function () { " +
                                    " $.datepicker.setDefaults($.extend( " +
                                    "	    $.datepicker.regional[\"ru\"]) " +
                                    "	  ); " +
                                    " $('#" + field.Key + "').datepicker({ " +
                                        " dateFormat: '" + dateFormatStringJQ + "', " +
                                        " showOn: 'button', " +
                                        " buttonImage: '" + urlHelper.Content("~/Content/Images/calendar.gif") + "', " +
                                        " buttonImageOnly: true, " +
                                        " onSelect: function(dateText, inst) { " +
                                        "	      $('#btnSearch').click();" +
                                        " } " +
                                    " }); " +
                                " }); " +
                                " </script> " +
                                "<input type='text' " + style + " id='" + field.Key + "' name='" + field.Key + "' " +
                                    " value = '" + ((value.HasValue) ? value.Value.ToString(dateFormatString) : "") + "'" +
                                " />");
                }
                else // Если столбец - не дата
                    builder.AppendLine("            <input id=\"" + field.Key + "\" name=\"" + field.Key + "\" value=\"" + field.Value + "\" " + style + " type=\"text\" />");

                if (colNum == 1) // Если первый столбец, то вставляется в него скрытая кнопка SUBMIT
                {
                    // Добавляется скрытая кнопка submit
                    builder.AppendLine("            <span style=\"visibility:hidden;width:0px;height:0px;\"><input type=\"submit\" style=\"width:0px;height:0px;\" id=\"btnSearch\" /></span>");
                }

                builder.AppendLine("        </th>");
                
            }

            builder.AppendLine("    </tr>");
            builder.AppendLine("</form>");

            #endregion Формируется строка с заголовком и поиском (форма GET)

            // ---------------------------------------------------------------------------------------------------------- //

            // ================================================
            // Формируются, строка с заголовками колонок грида
            // ================================================
            #region Формируются, строка с заголовками колонок грида

            builder.AppendLine("    <tr>");
            foreach (var field in fields)
            {
                TMP_ROUTE["orderBy"] = field.Key;
                builder.AppendLine("        <th>");
                builder.AppendLine("            <a href='" + urlHelper.RouteUrl(TMP_ROUTE) + "'" +
                                                    "class=\"next\">" + field.Key + "</a>" +
                        ((Model.GridSortOptions.Column == field.Key)
                            ? ("<span>" + (Model.GridSortOptions.Direction == SortDirection.Ascending ? "↑" : "↓") + "</span>") : ""));
                builder.AppendLine("        </th>");
            }
            builder.AppendLine("    </tr>");

            #endregion Формируются, строка с заголовками колонок грида

            // ---------------------------------------------------------------------------------------------------------- //

            // ================================================
            // Формируются, собственно строки грида
            // ================================================
            #region Формируются, собственно строки грида

            if (Model != null && Model.DataList != null && Model.DataList.Count > 0)
            {
                for (int i = 0; i < Model.DataList.Count(); i++)
                {
                    builder.AppendLine("    <tr>");
                    //Html.DisplayFor(model => model.DataList[i])
                    
                    foreach (var field in fields)
                    {
                        System.Reflection.PropertyInfo propertyInfo = typeof(TModel).GetProperty(field.Key);
                        builder.AppendLine("        <td>");
                        if (propertyInfo != null)
                        {
                            var value = propertyInfo.GetValue(Model.DataList[i], null);
                            builder.AppendLine(string.Format("            {0}", value));
                        }
                        builder.AppendLine("        </td>");
                    }
                    builder.AppendLine("    </tr>");
                }
            }
            else
            {
                builder.AppendLine(string.Format("<tr><td colspan=\"{0}\">Нет данных</td></tr>", fields.Count));
            }

            #endregion Формируются, собственно строки грида

            builder.AppendLine("</table>");


            return new MvcHtmlString(builder.ToString());

        }
    }
}
